package m

import (
	"GameServer/Common/utils"
	"fmt"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"

	"GameServer/Common/data"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
)

type Pet struct {
	Tid         int64   `bson:"tid" json:"tid"`
	Lv          int64   `bson:"lv" json:"lv"`
	Exp         int64   `bson:"exp" json:"exp"`
	Step        int64   `bson:"step" json:"step"`
	SkillVal    float64 `bson:"skillVal" json:"skillVal"`
	Star        int64   `bson:"star" json:"star"`
	LiveEndTime int64   `bson:"liveEndTime" json:"liveEndTime"`
	IsHave      bool    `bson:"isHave" json:"isHave"` // 是否拥有
	Status      int64   `bson:"status" json:"status"`
}

type UserPet struct {
	BaseM
	Uid       bson.ObjectId  `bson:"_id" json:"id"`
	Pets      map[int64]*Pet `bson:"pets" json:"pets"`
	ExpNum    int64          `bson:"expNum" json:"expNum"`
	FoodNum   int64          `bson:"foodNum" json:"foodNum"`
	SelectTid int64          `bson:"selectTid" json:"selectTid"`
}

func NewUserPet() cache.EntryI {
	return &UserPet{Pets: make(map[int64]*Pet, 0)}
}

// 保存信息
func (uPet *UserPet) Save() (err error) {
	mdata := make(map[string]interface{}, 0)

	mdata["expNum"] = uPet.ExpNum
	mdata["foodNum"] = uPet.FoodNum
	mdata["selectTid"] = uPet.SelectTid
	if uPet.Pets != nil && len(uPet.Pets) != 0 {
		mdata["pets"] = uPet.Pets
	}

	err = dbmodule.MgoDB.GameDB.Upsert("userPet", bson.M{"_id": uPet.Uid}, mdata)
	if err != nil {
		return
	}
	return
}

func (uPet *UserPet) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		uPet.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		uPet.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "UserPet_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return uPet.LoadData()
}

// 加载数据
func (uPet *UserPet) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("userPet", bson.M{"_id": uPet.Uid}, nil, &uPet)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return
	}

	if uPet.Pets == nil {
		uPet.Pets = make(map[int64]*Pet, 0)
	}
	return
}

// 更新数据
func (uPet *UserPet) Update(val *UserPet) {
	Cache.Put("userPet", uPet.Uid.Hex(), val)
	val.UpdateData()
}

func (uPet *UserPet) GetPet(tid int64) (pet *Pet, err error) {
	r, ok := uPet.Pets[tid]
	if !ok {
		err = errors.NewErrcode(data.Errcode.NoPet, fmt.Sprintf("没有这个宠物tid:%d", tid))
		return
	}
	if !r.IsHave {
		err = errors.NewErrcode(data.Errcode.NoPet, fmt.Sprintf("宠物还没有获取到:%d", tid))
		return
	}
	pet = r
	return
}

func (uPet *UserPet) AddFoodNum(num int64) (uPropPetInfo *UpdatePetInfo) {
	defer uPet.Update(uPet)
	uPet.FoodNum += num
	uPropPetInfo = &UpdatePetInfo{
		ExpNum:    uPet.ExpNum,
		FoodNum:   uPet.FoodNum,
		SelectTid: uPet.SelectTid,
	}
	return
}

func (uPet *UserPet) AddExpNum(num int64) (uPropPetInfo *UpdatePetInfo) {
	defer uPet.Update(uPet)
	uPet.ExpNum += num
	uPropPetInfo = &UpdatePetInfo{
		ExpNum:    uPet.ExpNum,
		FoodNum:   uPet.FoodNum,
		SelectTid: uPet.SelectTid,
	}
	return
}

func (uPet *UserPet) GetSkillVal(typ uint64) (val float64) {
	if uPet.SelectTid == 0 {
		return
	}

	pet, err := uPet.GetPet(uPet.SelectTid)
	if err != nil {
		return
	}

	if pet.LiveEndTime < utils.TNow().Unix() {
		return
	}

	petTpl, ok := data.Get("Pets", uint64(uPet.SelectTid))
	if !ok {
		return
	}
	petT := petTpl.(data.Pet)

	if petT.SkillEffect == typ {
		return pet.SkillVal
	}

	return
}

// 获取激活的宠物
func (uPet *UserPet) GetActivePet() (r *Pet) {
	if uPet.SelectTid == 0 {
		return
	}

	pet, err := uPet.GetPet(uPet.SelectTid)
	if err != nil {
		return
	}
	return pet
}

// 宠物星星数量
// func (uPet *UserPet) SumPetStar() (r int64) {
// 	r = 0
// 	for _, item := range uPet.Pets {
// 		if item.Status != 1 { // 没有激活不加
// 			continue
// 		}
// 		r += item.Star
// 	}
// 	return
// }

// func (uPet *UserPet) AddPet(tid int64) (kv *BaseKV, uPropPet *UpdatePet, uPropPetInfo *UpdatePetInfo, err error) {
// 	petTpl, ok := data.Get("Pets", uint64(tid))
// 	if !ok {
// 		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物配置tid:%d", tid))
// 		return
// 	}
// 	defer uPet.Update(uPet)
// 	petT := petTpl.(data.Pet)

// 	if pet, ok := uPet.Pets[tid]; ok {
// 		if pet.IsHave {
// 			err = errors.New("已经有这只宠物")
// 			return nil, nil, nil, err
// 		}
// 		// 升阶
// 		newStep := pet.Step + 1
// 		pSkillTpl, ok := data.Foreach(petT.SkillTpl, func(val interface{}) bool {
// 			val1 := val.(data.PetSkill)
// 			if int64(val1.Lv) == pet.Lv && int64(val1.Step) == newStep {
// 				return true
// 			}
// 			return false
// 		})
// 		if !ok {
// 			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置 lv:%d, step:%d", petT.SkillTpl, pet.Lv, newStep))
// 			return nil, nil, nil, err
// 		}

// 		// 宠物激活
// 		if pet.Status == 1 {
// 			kv = &BaseKV{Key: data.GlobalEnum.Star, Val: int64(pSkillTpl.(data.PetSkill).Star) - pet.Star}
// 		}
// 		pet.Star = int64(pSkillTpl.(data.PetSkill).Star)
// 		pet.Step = newStep
// 		pet.SkillVal = pSkillTpl.(data.PetSkill).SkillVal
// 		pet.IsHave = true
// 		uPropPet = &UpdatePet{
// 			Tid:         pet.Tid,
// 			Lv:          pet.Lv,
// 			Exp:         pet.Exp,
// 			Step:        pet.Step,
// 			SkillVal:    int64(pet.SkillVal * 1000), // 浮点型 保留3位小数
// 			LiveEndTime: pet.LiveEndTime,
// 		}
// 		if len(uPet.Pets) == 1 {
// 			uPet.SelectTid = tid
// 			uPropPetInfo = &UpdatePetInfo{
// 				ExpNum:    uPet.ExpNum,
// 				FoodNum:   uPet.FoodNum,
// 				SelectTid: uPet.SelectTid,
// 			}
// 			return kv, uPropPet, uPropPetInfo, nil
// 		}
// 		return kv, uPropPet, nil, nil
// 	}

// 	// 获得新的宠物

// 	skillTpl, ok := data.Get(petT.SkillTpl, uint64(1))
// 	if !ok {
// 		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置tid:%d", petT.SkillTpl, 1))
// 		return
// 	}
// 	skillT := skillTpl.(data.PetSkill)

// 	pet := &Pet{Tid: tid, Lv: 1, Exp: 0, Step: 1, Star: int64(skillT.Star), SkillVal: skillT.SkillVal, IsHave: true}

// 	// 首次获得
// 	if len(uPet.Pets) == 0 {
// 		uPet.SelectTid = tid
// 		uPropPetInfo = &UpdatePetInfo{
// 			ExpNum:    uPet.ExpNum,
// 			FoodNum:   uPet.FoodNum,
// 			SelectTid: uPet.SelectTid,
// 		}
// 	}
// 	uPet.Pets[tid] = pet
// 	uPropPet = &UpdatePet{
// 		Tid:         pet.Tid,
// 		Lv:          pet.Lv,
// 		Exp:         pet.Exp,
// 		Step:        pet.Step,
// 		SkillVal:    int64(pet.SkillVal * 1000),
// 		LiveEndTime: pet.LiveEndTime,
// 	}
// 	return
// }

// 增加宠物阶数
// func (uPet *UserPet) AddPetStep(tid int64, val int64) (uProp *UpdateProp, uPropPet *UpdatePet, err error) {
// 	petTpl, ok := data.Get("Pets", uint64(tid))
// 	if !ok {
// 		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物配置tid:%d", tid))
// 		return
// 	}
// 	defer uPet.Update(uPet)
// 	petT := petTpl.(data.Pet)
// 	uProp = NewUpdateProp()
// 	if pet, ok := uPet.Pets[tid]; ok {
// 		// 升阶
// 		newStep := pet.Step + val
// 		pSkillTpl, ok := data.Foreach(petT.SkillTpl, func(val interface{}) bool {
// 			val1 := val.(data.PetSkill)
// 			if int64(val1.Lv) == pet.Lv && int64(val1.Step) == newStep {
// 				return true
// 			}
// 			return false
// 		})
// 		if !ok {
// 			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置 lv:%d, step:%d", petT.SkillTpl, pet.Lv, newStep))
// 			return nil, nil, err
// 		}
// 		skillT := pSkillTpl.(data.PetSkill)
// 		fmt.Println("宠物升阶加星星:", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
// 		uProp.Kvs = append(uProp.Kvs, &BaseKV{Key: data.GlobalEnum.Star, Val: int64(skillT.Star) - pet.Star})

// 		pet.Star = int64(skillT.Star)
// 		fmt.Println("宠物升阶加星星 end:", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
// 		pet.Step = newStep
// 		pet.SkillVal = pSkillTpl.(data.PetSkill).SkillVal
// 		if !pet.IsHave {
// 			return uProp, nil, nil
// 		}

// 		uPropPet = &UpdatePet{
// 			Tid:         pet.Tid,
// 			Lv:          pet.Lv,
// 			Exp:         pet.Exp,
// 			Step:        pet.Step,
// 			SkillVal:    int64(pet.SkillVal * 1000),
// 			LiveEndTime: pet.LiveEndTime,
// 		}
// 		return uProp, uPropPet, nil
// 	}

// 	//
// 	skillTpl, ok := data.Get(petT.SkillTpl, uint64(1))
// 	if !ok {
// 		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置tid:%d", petT.SkillTpl, 1))
// 		return
// 	}
// 	skillT := skillTpl.(data.PetSkill)
// 	uProp.Kvs = append(uProp.Kvs, &BaseKV{Key: data.GlobalEnum.Star, Val: int64(skillT.Star)})
// 	pet := &Pet{Tid: tid, Lv: 1, Exp: 0, Star: int64(skillT.Star), Step: val, SkillVal: skillT.SkillVal, IsHave: false}
// 	uPet.Pets[tid] = pet
// 	return
// }

// 增加宠物阶数
// func (uPet *UserPet) ActivePet(tid int64) (uProp *UpdateProp, err error) {
// 	if pet, ok := uPet.Pets[tid]; ok {
// 		if pet.Status == 1 {
// 			return nil, nil
// 		}
// 		defer uPet.Update(uPet)
// 		uProp = NewUpdateProp()
// 		uProp.Kvs = append(uProp.Kvs, &BaseKV{Key: data.GlobalEnum.Star, Val: pet.Star})
// 		pet.Status = 1
// 		return
// 	}
// 	err = errors.NewErrcode(data.Errcode.NotFound, fmt.Sprintf("没有这个宠物：%d", tid))
// 	return
// }

// 增加宠物经验
// func (pet *Pet) AddExp(num int64) (uProp *UpdateProp, err error) {
// 	petTpl, ok := data.Get("Pets", uint64(pet.Tid))
// 	if !ok {
// 		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物配置tid:%d", pet.Tid))
// 		return
// 	}

// 	petT := petTpl.(data.Pet)
// 	if pet.Lv >= int64(petT.MaxLv) {
// 		return
// 	}
// 	num *= data.PetExpNum
// 	uProp = NewUpdateProp()
// 	for {

// 		expTpl, ok := data.Get(petT.ExpTpl, uint64(pet.Lv))
// 		if !ok {
// 			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物经验配置lv:%d", pet.Lv))
// 			return
// 		}
// 		expT := expTpl.(data.PetExp)
// 		if pet.Exp+num >= int64(expT.Exp) && pet.Lv < int64(petT.MaxLv) {
// 			pet.Lv++
// 			pSkillTpl, ok := data.Foreach(petT.SkillTpl, func(val interface{}) bool {
// 				val1 := val.(data.PetSkill)
// 				if int64(val1.Lv) == pet.Lv && int64(val1.Step) == pet.Step {
// 					return true
// 				}
// 				return false
// 			})
// 			if !ok {
// 				err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置 lv:%d, step:%d", petT.SkillTpl, pet.Lv, pet.Step))
// 				return nil, err
// 			}

// 			skillT := pSkillTpl.(data.PetSkill)

// 			uProp.Kvs = append(uProp.Kvs, &BaseKV{Key: data.GlobalEnum.Star, Val: int64(skillT.Star) - pet.Star})
// 			fmt.Println("宠物升级加星星 :", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
// 			pet.Star = int64(skillT.Star)
// 			fmt.Println("宠物升级加星星 end:", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
// 			num = pet.Exp + num - int64(expT.Exp)
// 			pet.SkillVal = pSkillTpl.(data.PetSkill).SkillVal
// 			pet.Exp = 0
// 			continue
// 		}
// 		pet.Exp += num
// 		break
// 	}
// 	return
// }

// func (pet *Pet) EatFood(num int64) (err error) {
// 	now := utils.TNow().Unix()
// 	if pet.LiveEndTime < now {
// 		pet.LiveEndTime = now
// 	}
// 	num *= data.PetFoodLiveTime
// 	if (num+pet.LiveEndTime)-now > 86400 {
// 		err = errors.NewErrcode(data.Errcode.ServerErr, fmt.Sprintf("宠物时间超过24小时, liveEndTime:%d", pet.LiveEndTime))
// 		return
// 	}

// 	pet.LiveEndTime += num
// 	return
// }

func (u *User) GetUserPet() (r *UserPet) {
	v, _ := Cache.Get("userPet", u.Uid.Hex())
	r = v.(*UserPet)
	return
}
